
import re
from openpyxl import Workbook
from openpyxl.styles import Font
from openpyxl.cell.rich_text import CellRichText, TextBlock

def html_to_rich_text(
    content, 
    style_color_dict={r'<span style="color:green">(.*?)</span>': "008000"}
):
    """
    将 content 中所有匹配 style_color_dict 的内容用指定颜色显示，其余为默认色。
    style_color_dict: key 为样式的正则表达式，value 为对应文本显示的颜色。
    返回 openpyxl 的 CellRichText 对象。
    """
    import re
    from openpyxl.cell.rich_text import CellRichText, TextBlock
    from openpyxl.cell.text import InlineFont

    # 记录所有匹配到的区块及其颜色
    matches = []
    for style_regex, color in style_color_dict.items():
        for m in re.finditer(style_regex, content, flags=re.DOTALL):
            matches.append({
                'start': m.start(),
                'end': m.end(),
                'text': m.group(1),
                'color': color,
                'priority': list(style_color_dict.keys()).index(style_regex)  # 保证顺序优先级
            })
    # 按起始位置排序，优先级高的在前
    matches.sort(key=lambda x: (x['start'], x['priority']))

    # 合并区块，避免重叠
    blocks = []
    last_idx = 0
    for m in matches:
        # 如果当前区块完全被前一个区块覆盖，则跳过
        if m['start'] < last_idx:
            if m['end'] <= last_idx:
                continue
            else:
                # 部分重叠，截断到 last_idx
                m_text_start = last_idx - m['start']
                m_text = m['text'][m_text_start:]
                blocks.append({'text': m_text, 'color': m['color']})
                last_idx = m['end']
                continue
        if m['start'] > last_idx:
            blocks.append({'text': content[last_idx:m['start']], 'color': None})
        blocks.append({'text': m['text'], 'color': m['color']})
        last_idx = m['end']
    if last_idx < len(content):
        blocks.append({'text': content[last_idx:], 'color': None})

    # 构建富文本
    rich = CellRichText()
    for b in blocks:
        if b['text']:
            if b['color']:
                rich.append(TextBlock(text=b['text'], font=InlineFont(color=b['color'])))
            else:
                rich.append(TextBlock(text=b['text'], font=InlineFont()))
    return rich
